#include "Request.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

static char* s_post		= NULL;

#define MAX_CONTENT_LENGTH		409600

char hex2char(char c)
{
	if(c >= '0' && c <= '9')
	{
		return c - '0';
	}
	else if(c >= 'a' && c <= 'f')
	{
		return c - 'a' + 10;
	}
	else if(c >= 'A' && c <= 'F')
	{
		return c - 'A' + 10;
	}
	else
	{
		return 0;
	}
}
/*
 * 从key=value中获取值
 */
bool http::getValue(const char* str, const char* key, std::string& value)
{
	const char*		next	= str;

	while(true)
	{
		const char*		p0;
		const char*		p1;
		const char*		p2;

		// 查找关键字
		p1 = strcasestr(next, key);
		if(NULL == p1)
		{
			return false;
		}

		// 验证关键字
		p0 = p1;
		p1 += strlen(key);
		if( (p0 == str || '&' == *(p0 - 1))
			&& ('&' == *p1 || '\x0' == *p1) )
		{
			// 找到了关键字，但是没有数据
			value.clear();
			return true;
		}
		else if('=' != *p1)
		{
			next = p1;
			continue;
		}

		// 查找结束标志
		p1++;
		p2 = strchr(p1, '&');
		if(NULL == p2)
		{
			p2 = p1 + strlen(p1);
		}

		// 解析值
		decodeUri(p1, p2, value);
		return true;
	}

	return false;
}

/*
 * 解码URI
 */
void http::decodeUri(const char* start, const char* end, std::string& ret)
{
	ret.clear();
	for( ; start < end; start++)
	{
		// %号要进行转码
		if( '%' == *start
			&& ((start + 2) < end ) )
		{
			char	c	= 0;
			c |= hex2char(*(start + 1)) << 4;
			c |= hex2char(*(start + 2));
			ret.push_back(c);
			start += 2;
			continue;
		}
		
		// 把+号转换为空格
		if( '+' == *start )
		{
			ret.push_back('\x20');
			continue;
		}
		// 非%号就直接插入
		// 或者是%号后的字符不足以表示一个十六进制
		ret.push_back(*start);
	}
}

/*
 * 重置
 */
void request::reset()
{
	if(NULL != s_post)
	{
		free(s_post);
		s_post = NULL;
	}
}

/*
 * 获取HTTP GET数据
 */
bool request::get(const char* name, std::string& value)
{
	char*		query	= getenv("QUERY_STRING");

	if(NULL == query)
	{
		return false;
	}

	return http::getValue(query, name, value);
}

/*
 * 获取HTTP POST数据
 */
bool request::post(const char* name, std::string& value)
{
	if(NULL == s_post)
	{
		char*			method		= getenv("REQUEST_METHOD");
		char*			type		= getenv("CONTENT_TYPE");
		char*			length		= getenv("CONTENT_LENGTH");
		int				len;
		
		if(NULL == method || NULL == type || NULL == length)
		{
			return false;
		}

		if(strcasecmp(method, "POST") != 0
				|| strcasecmp(type, "application/x-www-form-urlencoded") != 0)
		{
			return false;
		}

		len = atoi(length);
		if(len <= 0 || len > MAX_CONTENT_LENGTH)
		{
			return false;
		}

		s_post = (char *)malloc(len + 1);
		memset(s_post, len + 1, 0);
		fread(s_post, len, 1, stdin);
	}

	return http::getValue(s_post, name, value);
}

/*
 * 获取上传的文件
 */
bool request::file(const char* name, std::string& value)
{
	return false;
}

/*
 * 读取文件
 */
char* sys::readFile(const char* path)
{
	int				fd;
	struct stat		st		= {0};
	char*			buf;

	// 打开文件
	fd = open(path, O_RDONLY);
	if(-1 == fd)
	{
		return NULL;
	}

	// 读取文件
	fstat(fd, &st);
	buf = (char *)malloc(st.st_size + 1);
	if(NULL != buf)
	{
		memset(buf, 0, st.st_size + 1);
		read(fd, buf, st.st_size);
	}

	// 关闭文件
	close(fd);
	return buf;
}

/*
 * 解析配置文件
 */
void sys::parseConfig(char* buffer, void (*callback)(const char*, const char*))
{
	char*		lstart		= buffer;
	char*		lend;
	char*		key;
	char*		value;

	while(0 != *lstart)
	{
		// erase space
		while('\n' == *lstart || '\x20' == *lstart 
				|| '\t' == *lstart)
		{
			lstart++;
		}

		// find end
		lend = strchr(lstart, '\n');
		if(NULL == lend)
		{
			lend = lstart + strlen(lstart);
		}

		// 跳过注释
		if('#' == *lstart)
		{
			lstart = lend;
			continue;
		}

		// 开始分析key=value
		key = lstart;
		lstart = lend;
		// 分离等号
		lend = strchr(key, '=');
		if(NULL == lend || lend > lstart)
		{
			continue;
		}

		// 清除KEY的尾部空格
		value = lend + 1;
		while('\t' == *(lend - 1)
				|| '\x20' == *(lend - 1))
		{
			lend--;
		}

		*lend = 0;
		// 分析value
		while('\t' == *value || '\x20' == *value)
		{
			value++;
		}

		// 清除尾部的空格
		lend = lstart;
		while('\x20' == *(lend - 1) 
				|| '\t' == *(lend - 1)
				|| '\r' == *(lend - 1))
		{
			lend--;
		}

		// 重调指向下一行的标识
		if('\n' == *lend)
		{
			lstart++;
		}

		*lend = 0;
		// 调用回调函数
		callback(key, value);
	}
}

extern MYSQL* g_mysql;
/*
 * 执行更新语句
 * 返回受影响行数
 */
long sql::execute(const char* sql)
{
	long		ret;
	MYSQL_RES	*res;

	if(0 != mysql_query(g_mysql, sql))
	{
		return 0;
	}

	ret = mysql_affected_rows(g_mysql);
	// 清空缓存
	res = mysql_store_result(g_mysql);
	if(NULL != res)
	{
		mysql_free_result(res);
	}

	return ret;
}

/*
 * 查询sql
 */
bool sql::query(const char* sql, bool (*callback)(void* context, int r, int c, MYSQL_ROW row), void* context)
{
	MYSQL_RES			*res;
	MYSQL_ROW			row;
	int					col;
	bool				ret;

	if(0 != mysql_query(g_mysql, sql))
	{
		return false;
	}

	res = mysql_store_result(g_mysql);
	if(NULL == res)
	{
		return false;
	}

	col = mysql_num_fields(res);
	ret = (0 != mysql_num_rows(res)) ? true : false;
	// 输出查询的结果
	for(int i = 0; row = mysql_fetch_row(res); i++)
	{
		if(false == callback(context, i, col, row))
		{
			break;
		}
	}

	mysql_free_result(res);
	return ret;
}

bool signalQueryCallback(void* context, int i, int col, MYSQL_ROW row)
{
	va_list*		var		= (va_list *)context;

	for(int k = 0; k < col; k++)
	{
		std::string*	str	= va_arg(*var, std::string*);

		if(NULL == str)
		{
			break;
		}

		*str = row[k];
	}

	return false;
}
/*
 * 执行一行的查询
 */
bool sql::signalQuery(const char* sql, ...)
{
	va_list		var;
	bool		ret;

	va_start(var, sql);
	ret = sql::query(sql, signalQueryCallback, &var);
	va_end(var);
	return ret;
}
